package com.newbe.security.config;

import com.newbe.security.handler.MyAuthenticationFailureHandler;
import com.newbe.security.handler.MyAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /** 具体流程：
     *1. 开启@EnableWebSecurity，让SecurityConfig extends WebSecurityConfigurerAdapter
     *2. 分别重写void configure(AuthenticationManagerBuilder auth)、void configure(HttpSecurity http)
     *3、在void configure(HttpSecurity http)方法里设置拦截资源，对资源进行认证命名
     *4、在void configure(HttpSecurity http)方法里设置登录界面放行，formLogin认证方式，并设置登陆界面路径，关闭csrf
     *5、在void configure(HttpSecurity http) 方法里设置账号，对其赋予权限
     *6、启动项目，测试：127.0.0.1:8080,分别进行管理员和用户的登录操作订单
     *7、增加权限错误和成功提示，思路：
     *7.1分别定义SuccessHandler类和FailureHandler类让他们实现AuthenticationSuccessHandler类
     *    重新其中的方法，在该方法定义成功和失败的处理流程。目前只简单的对成功和失败认证在控台打印信息
     *7.2 利用 ConfigurableServletWebServerFactory 设置状态码和设置错误路径控制器，控制错误页面
     **/
    @Autowired
    MyAuthenticationFailureHandler FailureHandler;
    @Autowired
    MyAuthenticationSuccessHandler SuccessHandler;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //4.设置管理员账号和密码，对其赋予权限authorities
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("admin")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("ADMIN").authorities("deleteOrder","addOrder","showOrder","updateOrder");

        //5.设置用户账号和密码，对其赋予权限authorities
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("user").password(new BCryptPasswordEncoder()
                .encode("123456")).roles("USER").authorities("showOrder","addOrder");
    }
     @Override
    protected void configure(HttpSecurity http) throws Exception {
        //1.对页面资源进行拦截和命名
        http.authorizeRequests().antMatchers("/showOrder").hasAnyAuthority("showOrder");
        http.authorizeRequests().antMatchers("/addOrder").hasAnyAuthority("addOrder");
        http.authorizeRequests().antMatchers("/deleteOrder").hasAnyAuthority("deleteOrder");
        http.authorizeRequests().antMatchers("/updateOrder").hasAnyAuthority("updateOrder");

        //2.对登录界面允许所有用户访问
        http.authorizeRequests().antMatchers("/login").permitAll();

        //3.资源需要进行登录认证，且关闭跨域允许post表单请求，loginProcessingUrl：表单路径，loginPage：登录界面
        http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().formLogin()
                .loginPage("/login").loginProcessingUrl("/loginFrom")
                //添加成功和失败处理器
                .successHandler(SuccessHandler).failureHandler(FailureHandler)
                .and().csrf().disable();
    }

}